<?php
class XDBXA{
	private static $instance = null;
	private $xid = null;
	private $xids = array();
	private $resources = array();
	
	private function __construct() {
	
	}

	/**
	 * @return XDBXA
	 */	
	static function singleton() {
		if (!self::$instance) {
			self::$instance = new self;
		}
		return self::$instance;
	}
	
	public function invokeArgs(XDBXAResource $resource, $method, $args){
		if(XClassLoader::loader('XDBXAResource')->hasMethod($method)){			
			return XFactory::singleton()->invokeArgs($resource, $method, $args);
		}
		$rmUID = $resource->rmUID();
		if($this->xid
			&& !isset($this->xids[$rmUID])
			&& !$resource->xaStarted()){
			$resource->startXA($this->xid);
			$this->xids[$rmUID] = $this->xid;
			$this->resources[] = $resource;
		}
		return XFactory::singleton()->invokeArgs($resource, $method, $args);
	}
	
	public function startXA($flags = null){
		if(!$this->xid){
			$this->xid = md5(time().rand(1,100));
		}
		return true;
	}
	
	public function prepareXA(){
		if(!$this->xid
			|| empty($this->resources)){
			return true;
		}
		foreach($this->resources as $resource){
			$resource->endXA($this->xid);
			$resource->prepareXA($this->xid);
		}
		return true;
	}
	
	public function recoverXA($flag = null){
		if(!$this->xid
			|| empty($this->resources)){
			return true;
		}
		foreach($this->resources as $resource){
			$resource->recoverXA($flag);
		}
		return true;		
	}	
	
	public function rollbackXA(){
		if(!$this->xid
			|| empty($this->resources)){
			return true;
		}
		foreach($this->resources as $resource){
			$resource->rollbackXA($this->xid);
		}
		return true;		
	}
	
	public function commitXA($onePhase = null){
		if(!$this->xid
			|| empty($this->resources)){
			return true;
		}
		foreach($this->resources as $resource){
			$resource->commitXA($this->xid, $onePhase);
		}
		return true;		
	}
}
?>